#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
__title__ = ''
__author__ = 'python'
__mtime__ = '18-9-8'
# code is far away from bugs with the god animal protecting ~
"""

import pickle

from flask import render_template, current_app, g, request, jsonify, abort

from info import constants, redis_server, db
from info.models import User, News, Category, Comment
from info.response_code import RET, error_map
from info.utils.common import required_login, general_msg
from . import bp_index as app


# 主页详情
@app.route("/", methods=['GET', 'POST'])
@required_login
def index():
	# session['user'] = "the session user~"
	user = g.user
	categorys = None

	# 新闻排序信息
	# 先从Redis中查到是否有新闻排序信息
	news_order = redis_server.get("news_order_buffer")
	if news_order:
		news_order = pickle.loads(news_order)

	try:
		# 如果没有则从Mysql数据库中查询
		if not news_order:
			news_order = News.query.filter(News.status == 1).order_by(News.clicks.desc()).limit(
				constants.CLICK_RANK_MAX_NEWS)
			if news_order:
				news_order = [(news.id, news.title) for news in news_order]
				redis_server.setex("news_order_buffer", constants.NEWS_ORDER_REDIS_EXPIRES, pickle.dumps(news_order))
		# 这里返回目录详情信息
		categorys = Category.query.all()
	except Exception as e:
		current_app.logger.error(e)
		return general_msg(RET.DBERR, "MySql数据库查询错误")

	# user_id 用于判断用户是否登录, nick_name 用于显示昵称
	data = {"user_id": user.id if user else None, "news_order": news_order,
			"categorys": [category.name for category in categorys]}

	if user:
		data.update(user.to_dict())

	return render_template("news/index.html", **data)


# 响应index主页中的ajax请求,按目录返回新闻列表
@app.route("/news_list", methods=["GET"])
def news_list():
	get_para = request.args

	try:
		# cid为新闻目录id,page为请求第几页信息
		cid = int(get_para.get("cid", None))
		page = int(get_para.get("page", 1))
	except Exception as e:
		return general_msg(RET.PARAMERR)

	filter_list = []
	if cid > 1:
		filter_list.append(News.category_id == cid)

	filter_list.append(News.status == 1)

	paginate = None
	try:
		paginate = News.query.filter(*filter_list).order_by(News.create_time.desc()).paginate(page,
																							  constants.HOME_PAGE_MAX_NEWS,
																							  False)
	except Exception as e:
		current_app.logger.error(e)
		return general_msg(RET.DBERR, "MySql数据库查询错误")

	param = {"errno": RET.OK, "errmsg": error_map[RET.OK],
			 "data": {"total_page": paginate.pages, "news_dict_list": [news.to_dict() for news in paginate.items]}}

	return jsonify(param)


# 返回新闻详情页
@app.route("/<int:num>")
@required_login
def news_detail(num):
	user = g.user
	news = author = comments = None
	isfollower = iscollection = False

	try:
		news = News.query.filter_by(id=num).first()
		author = news.user

		if user and news in user.collection_news:
			iscollection = True

		if author:
			followers = author.followers
			isfollower = True if user in followers else False
	except Exception as e:
		current_app.logger.error(e)
		raise abort(404)
		return

	# 先从Redis中查到是否有新闻排序信息
	news_order = redis_server.get("news_order_buffer")
	if news_order:
		news_order = pickle.loads(news_order)

	try:
		# 如果没有则从Mysql数据库中查询
		if not news_order:
			news_order = News.query.filter(News.status == 1).order_by(News.clicks.desc()).limit(
				constants.CLICK_RANK_MAX_NEWS)
			if news_order:
				news_order = [(news.id, news.title) for news in news_order]
				redis_server.setex("news_order_buffer", constants.NEWS_ORDER_REDIS_EXPIRES, pickle.dumps(news_order))
		# 查出新闻对应的评论
		comments = Comment.query.filter_by(news_id=news.id, parent_id=None).order_by(Comment.create_time.desc()).all()
	except Exception as e:
		current_app.logger.error(e)
		return general_msg(RET.DBERR, "MySql数据库查询错误")

	news.clicks += 1
	try:
		db.session.add(news)
		db.session.commit()
	except Exception as e:
		db.session.rollback()
		current_app.logger.error(e)
		return general_msg(RET.DBERR)

	user_dict = user.to_dict() if user else None

	data = {"user_id": user.id if user else None, "nick_name": user.nick_name if user else None,
			"news_order": news_order, "author": author.to_dict() if author else None, "isfollower": isfollower,
			"iscollection": iscollection, "user": user_dict,
			"avatar_url": user_dict.get("avatar_url", None) if user else None,
			"comments": [comment.to_dict(user) for comment in comments], "news": news.to_dict() if news else None}

	# print( [comment.to_dict() for comment in comments])
	return render_template("news/detail.html", **data)


# 收藏接口
@app.route("/news_collect", methods=["POST"])
@required_login
def news_collect():
	user = g.user

	# 如果没有用户,直接返回消息给前端处理
	if not user:
		return general_msg(RET.SESSIONERR)

	get_para = request.json

	news_id = get_para.get("news_id", None)
	action = get_para.get("action", None)

	if not all([news_id, action]):
		return general_msg(RET.PARAMERR)

	news = News.query.get(news_id)
	if not news:
		return general_msg(RET.PARAMERR, "新闻ID错误")

	user_collections = user.collection_news
	if action == "collect":
		# 如果点击收藏,那么先判断是否已经收藏,已收藏返回错误,未收藏则写入数据库
		if news in user_collections:
			return general_msg(RET.DATAEXIST)
		else:
			user_collections.append(news)
	elif action == "cancel_collect":
		if news not in user_collections:
			return general_msg(RET.DATAERR, "用户未收藏")
		else:
			user_collections.remove(news)

	try:
		db.session.add(user)
		db.session.commit()
	except Exception as e:
		db.session.rollback()
		current_app.logger.error(e)
		return general_msg(RET.DBERR)

	return general_msg(RET.OK)


# 用户关注接口
@app.route("/followed_user", methods=["POST"])
@app.route("/users/followed_user", methods=["POST"])
@required_login
def followed_user():
	user = g.user

	# 如果没有用户,直接返回消息给前端处理
	if not user:
		return general_msg(RET.SESSIONERR)

	get_para = request.json

	author_id = get_para.get("user_id", None)
	action = get_para.get("action", None)

	if not all([author_id, action]):
		return general_msg(RET.PARAMERR)

	try:
		author = User.query.get(author_id)
	except Exception as e:
		current_app.logger.error(e)
		return general_msg(RET.DBERR)

	if not author:
		return general_msg(RET.USERERR, "作者不存在")

	if action == "follow":
		print(user.id, author_id)
		if user.id == author.id:
			return general_msg(RET.DATAERR, "不能关注自己")
		else:
			author.followers.append(user)
	elif action == "unfollow":
		if user not in author.followers:
			return general_msg(RET.DATAERR, "未关注该作者")
		else:
			author.followers.remove(user)

	try:
		db.session.add(author)
		db.session.commit()
	except Exception as e:
		db.session.rollback()
		current_app.logger.error(e)
		return general_msg(RET.DBERR)

	return general_msg(RET.OK)


# 用户评论接口
@app.route("/news_comment", methods=["POST"])
@required_login
def news_comment():
	user = g.user

	# 如果没有用户,直接返回消息给前端处理
	if not user:
		return general_msg(RET.SESSIONERR)

	get_para = request.json

	news_id = get_para.get("news_id", None)
	comment_content = get_para.get("comment", None)
	parent_id = get_para.get("parent_id", None)

	if not all([news_id, comment_content]):
		return general_msg(RET.PARAMERR)

	news = comment_parent = None
	try:
		news = News.query.get(news_id)
		if parent_id:
			comment_parent = Comment.query.get(parent_id)
	except Exception as e:
		current_app.logger.error(e)
		return general_msg(RET.DBERR)

	if not news:
		return general_msg(RET.PARAMERR, "没有这条新闻")

	print(news.id)
	comment = Comment()
	comment.user_id = user.id
	comment.news_id = news.id
	comment.content = comment_content
	if comment_parent:
		comment.parent_id = parent_id

	try:
		db.session.add(comment)
		db.session.commit()
	except Exception as e:
		db.session.rollback()
		current_app.logger.error(e)
		return general_msg(RET.DBERR)

	param = {"errno": RET.OK, "errmsg": "OK", "data": comment.to_dict(), }

	return jsonify(param)


# 用户评论点赞接口
@app.route("/comment_like", methods=["POST"])
@required_login
def comment_like():
	user = g.user

	# 如果没有用户,直接返回消息给前端处理
	if not user:
		return general_msg(RET.SESSIONERR)

	get_para = request.json

	comment_id = get_para.get("comment_id", None)
	action = get_para.get("action", None)

	if not all([comment_id, action]):
		return general_msg(RET.PARAMERR)

	try:
		comment = Comment.query.get(comment_id)
	except Exception as e:
		current_app.logger.error(e)
		return general_msg(RET.DBERR)

	if not comment:
		return general_msg(RET.DATAERR, "评论不存在")

	if action == "add":
		if user in comment.users.all():
			return general_msg(RET.DATAERR, "已经赞过了")
		else:
			comment.users.append(user)
			comment.like_count = comment.users.count()
	elif action == "remove":
		if user not in comment.users.all():
			return general_msg(RET.DATAERR, "还没有赞过这条评论")
		else:
			comment.users.remove(user)
			comment.like_count = comment.users.count()

	try:
		db.session.add(comment)
		db.session.commit()
	except Exception as e:
		db.session.rollback()
		current_app.logger.error(e)
		return general_msg(RET.DBERR)

	return general_msg(RET.OK)


@app.route("/favicon.ico", methods=["GET"])
def get_favicons():
	return current_app.send_static_file('news/favicon.ico')


# 404错误处理，这里的视图函数需要传递一个e的参数
@app.errorhandler(404)
def error_handle(e):
	user = g.user
	data = {"user_id": user.id if user else None, "nick_name": user.nick_name if user else None}

	return render_template("news/404.html", **data)


if __name__ == '__main__':
	pass
